﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Description;
using System.Xml;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Reflection;
using System.ServiceModel;

namespace ExecutionContract
{
    [AttributeUsage(AttributeTargets.Interface)]
    public class ExecutionContractAttribute : Attribute,
        IWsdlExportExtension, IContractBehavior
    {
        #region Properties
        /// <summary>
        /// This is the object that goes through all relevant types and checks if the type contains any annotations that are relevant for the ExecutionContractGeneration.
        /// </summary>

        //maybe public? (was ist das englische wort für zugriffsmodifizierer?)
        protected IExecutionContractReader TypeReader { get; set; }

        #endregion

        #region Constructors
        /// <summary>
        /// This is the default constructor of the ExecutionContract. If you use this constructor ExecutionContractReader will be used as TypeReader.
        /// </summary>
        public ExecutionContractAttribute()
        {
            TypeReader = new ExecutionContractReader();
        }

        #endregion

        #region Public Methods

        public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
        {
            //to avoid null pointer during call of OwnerDocument
            context.WsdlPortType.Documentation = string.Empty;

            XmlElement owner = context.WsdlPortType.DocumentationElement;
            //XmlElement summaryElement = owner.CreateElement("CodeInjection");

            Type contract = context.Contract.ContractType;

            //Get all methods of the service to look up executioncontracts in the input and return parameters
            foreach (MethodInfo methodInfo in contract.GetMethods())
            {
                //Get all input parameters to look up executioncontracts
                foreach (ParameterInfo parameterInfo in methodInfo.GetParameters())
                {
                    //Generate the code
                    TypeReader.Add(parameterInfo.ParameterType);
                }

                //go through Outputparameters
                TypeReader.Add(methodInfo.ReturnType);
            }
            List<ExecutionContract> ListToWrite = TypeReader.Read();

            ExecutionContractWriter Writer = new ExecutionContractWriter(owner);

            Writer.Write(ListToWrite);
        }

        public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
        {           

        }

        //no idea why I have to implement these interface, but without, it isn't work
        public void AddBindingParameters(ContractDescription description, ServiceEndpoint endpoint, BindingParameterCollection parameters)
        {
            return;
        }

        public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, ClientRuntime proxy)
        {
            return;
        }

        public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)
        {
            return;
        }

        public void Validate(ContractDescription description, ServiceEndpoint endpoint)
        {
            return;
        }

        #endregion
    }
}